﻿using System.ComponentModel;
using System.Windows;
using System.Windows.Forms.Integration;
using StepsManagerLibrary.Enum;
using StepsManagerLibrary.Interfaces;

namespace StepsManagerUILibrary
{
    /// <summary>
    /// Interaction logic for UntypedUserControl.xaml
    /// </summary>
    public partial class UntypedUserControl : BaseWPFUserControl
    {
        #region Fields

        private readonly BaseWPFUserControl _innerUserControl;
        private readonly BaseWinformUserControl _winformUserControl;
        private readonly WindowsFormsHost _winformHost;

        #endregion

        #region Properties

        /// <summary>
        /// ConcreteControl hosted by the UntypedUserControl
        /// </summary>
        public FrameworkElement InnerControl
        {
            get
            {
                if (_innerUserControl != null)
                    return _innerUserControl;

                return _winformHost;
            }
        }

        /// <summary>
        /// Get the current control
        /// </summary>
        protected IStepControl _control
        {
            get
            {
                // Based on the type of object we host
                // We expect to provide a WPF UserControl
                // Or a WinformHost hosting a Winform UserControl
                if (_innerUserControl != null)
                    return _innerUserControl;

                return _winformUserControl;
            }
        }

        #endregion

        #region Constructors

        private UntypedUserControl()
            : base("")
        {
            InitializeComponent();
        }

        private UntypedUserControl(string title)
            : base(title)
        {
            InitializeComponent();

            this.DataContext = this;
        }

        #region Constructor from WPF Control

        public UntypedUserControl(BaseWPFUserControl wpfControl)
            : this(wpfControl.Title)
        {
            _innerUserControl = wpfControl;
            _winformUserControl = null;

            // Register the PropertyChanged event
            _innerUserControl.PropertyChanged += InvokePropertyChanged;
        }

        #endregion

        #region Constructor from Winform Control

        public UntypedUserControl(BaseWinformUserControl winformControl)
            : this(winformControl.Title)
        {
            _innerUserControl = null;
            _winformUserControl = winformControl;

            // Hosting the Winform element in a WPF control
            _winformHost = new WindowsFormsHost { Child = _winformUserControl };

            // Register the PropertyChanged event
            _winformUserControl.PropertyChanged += InvokePropertyChanged;
        }

        #endregion

        #endregion

        #region IStepControl Members

        /// <summary>
        /// Retuen the title of the InnerControl
        /// </summary>
        public override string Title
        {
            get { return _control.Title; }
        }

        public override StepControlStateEnum State
        {
            get { return _control.State; }
            set { _control.State = value; }
        }

        public override bool Initialize()
        {
            return _control.Initialize();
        }

        public override bool CanMoveIn()
        {
            return _control.CanMoveIn();
        }

        public override bool CanMoveOut()
        {
            return _control.CanMoveOut();
        }

        public override bool BeforeMovingIn()
        {
            return _control.BeforeMovingIn();
        }

        public override bool MoveIn()
        {
            return _control.MoveIn();
        }

        public override bool AfterMovingIn()
        {
            return _control.AfterMovingIn();
        }

        public override bool BeforeMovingOut()
        {
            return _control.BeforeMovingOut();
        }

        public override bool MoveOut()
        {
            return _control.MoveOut();
        }

        public override bool AfterMovingOut()
        {
            return _control.AfterMovingOut();
        }

        #endregion

        #region INotifyPropertyChanged Members

        /// <summary>
        /// Sending the event of the inner control directly from the host component
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="propertyChangedEventArgs"></param>
        private void InvokePropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
        {
            OnPropertyChanged(propertyChangedEventArgs.PropertyName);
        }

        #endregion

        #region IObservable<StepControlStateEnum> Members

        public override void Attach(IObserver<StepControlStateEnum> observer)
        {
            _control.Attach(observer);
        }

        public override void Detach(IObserver<StepControlStateEnum> observer)
        {
            _control.Detach(observer);
        }

        public override void Notify(StepControlStateEnum notification)
        {
            _control.Notify(notification);
        }

        #endregion
    }
}